#ifndef __MOYING_COMMU_PUBLISH_H__
#define __MOYING_COMMU_PUBLISH_H__
#include <moying_comm_lib/moying_commu_base.h>
#include <memory>
#include <mutex>
#include <queue>
#include <moying_comm_lib/waiter.h>
namespace moying
{
namespace communication
{

struct PubData // 发布数据结构
{
  std::string content_;
  bytes_ptr data_;
  bool log_;

  PubData(const std::string &content, const bytes_ptr &data, bool log) :
  content_(content), data_(data), log_(log)
  {
  }
};

class MoyingCommuPublish : public MoyingCommuBase
{
public:
  MoyingCommuPublish(const std::string &url, const std::string &identity);
  MoyingCommuPublish(const std::string &ip, const unsigned int port, const std::string &identity);
  ~MoyingCommuPublish() noexcept;

  template <typename M>
  bool publish(const std::string &content, M raw_data, bool log = true)
  {
    ::google::protobuf::Message *msg = &raw_data;
    std::string msg_str;
    msg->SerializeToString(&msg_str);
    if(proto_types_.find(content) == proto_types_.end())
      proto_types_[content] = new M();
    bytes_ptr data = std::make_shared<bytes_vec>(msg_str.data(),msg_str.data() + msg_str.length());
    std::lock_guard<std::mutex> lk(mutex_pub_queue_);
    queue_pub_.emplace(content, data, log);
    wait_pub_queue_.broadcast();
    return true;
  }

  virtual bool run() override;
  virtual bool close() override;

private:
  void createLoop();
  void clearPublishQueue();
  void printPackWrapper(const std::string &content, bytes_ptr pack, int thread_id);

private:
//  zmq::context_t ctx_;            // 上下文环境
  zmq::socket_t socket_;          // 套接字对象
  Waiter wait_pub_queue_;         // 等待发布队列非空
  std::mutex mutex_pub_queue_;    // 发布队列互斥量
  std::queue<PubData> queue_pub_; // 待发布数据队列
  const int kSendQueueHWM = 1000; // 待发布数据最大数量
  std::map<std::string, ::google::protobuf::Message*> proto_types_;
};

typedef std::shared_ptr<MoyingCommuPublish> MoyingCommuPublishPtr;

} // communication
} // namespace moying

#endif // __MOYING_COMMU_PUBLISH_H__
